package org.geekbang.thinking.in.spring.data.binding;

import org.geekbang.thinking.in.spring.ioc.overview.domain.Company;
import org.geekbang.thinking.in.spring.ioc.overview.domain.User;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.validation.BindingResult;
import org.springframework.validation.DataBinder;

import java.util.HashMap;

/**
 * {@link DataBinder} 示例
 *
 * @author wangyh2
 * @version v1.0
 * @since 2021-11-11 14:38
 */
public class DataBinderDemo {
    public static void main(String[] args) {
        // 1, 创建空白对象
        User user = new User();
        // 2, 创建 DataBinder
        DataBinder binder = new DataBinder(user, "");
        // 3, 创建 PropertyValues
        HashMap<String, Object> source = new HashMap<>();
        source.put("id", 1);
        source.put("name", "sishen007");
        // test1 忽略未知属性
        test1(source);
        // test2 支持嵌套属性
        test2(source);
        // test3 调整bind策略
        test3(binder);
        PropertyValues propertyValues = new MutablePropertyValues(source);
        binder.bind(propertyValues);
        // 4. 输出 User 内容
        System.out.println(user);
        // 5. 获取绑定结果（结果包含错误文案 code，不会抛出异常）
        BindingResult bindingResult = binder.getBindingResult();
        System.out.println(bindingResult);
    }

    /**
     * 调整binder策略
     *
     * @param binder
     */
    private static void test3(DataBinder binder) {
        // 1. 调整 IgnoreUnknownFields true（默认） -> false（抛出异常，age 字段不存在于 User 类）
        // binder.setIgnoreUnknownFields(false);

        // 2.调整自动增加嵌套路径 true（默认） —> false
        // 需要先设置 user.setCompany(new Company()); 不然直接设置嵌套属性值会报错
        binder.setAutoGrowNestedPaths(false);

        // 3. 调整 ignoreInvalidFields false(默认） -> true（默认情况调整不变化，需要调增 AutoGrowNestedPaths 为 false）
        binder.setIgnoreInvalidFields(true);

        // 4. 设置必填字段
        binder.setRequiredFields("id", "name", "city");
    }

    /**
     * 特性二：支持嵌套属性
     *
     * @param source
     */
    private static void test2(HashMap<String, Object> source) {
        source.put("company.name", "微医");
    }

    /**
     * 特性一 : 忽略未知的属性
     *
     * @param source
     */
    private static void test1(HashMap<String, Object> source) {
        source.put("age", 10);
    }


}
